function getBookListing(renderTo,url) {
    var ret = new CRUDrenderer(renderTo,url);

    ret.renderRead = function() {
        CRUDrenderer.prototype.renderRead.call(this);
        if (this.afterRender) {
            this.afterRender();
        }
    }

    ret.readRenderer = function(type,data) {
        if (type == "wrapper") {
            return $('<div class="booksDiv"/>');
        }
        return null;
    };

    ret.recordRenderer = function(type,data) {
        if (type == "recordWrapper") {
            return $('<div class="bookDiv" id="book'+data+
                '" style="margin-top:10px;"></div>');
        } else if (type == "record") {
            var self = this;
            var category = "";
            if (data.category != undefined) {
                category = data.category.name;
            }
            var link = $('<a href="">'+data.title+'</a>');
            link.click( function() {
                self.showBook(data.id);
                return false;
            });
            var newReviewForm = $('<form></form>',{
                method: 'post',
                action: 'controllers/reviews.php'
            });
            newReviewForm.append(
                '<input type="hidden" name="book_id" value="'+data.id+'">');
            newReviewForm.append(
                '<p><textarea rows="5" cols="20" name="text"/></p>');
            newReviewForm.append(
                '<p><input type="submit" name="add_review" value="send"></p>');
            newReviewForm.hide();
            newReviewForm.ajaxForm({
                dataType: 'json',
                success: function(data) {
                    if (data && data.error) {
                        alert(data.error); 
                    } else {
                        self.refreshRead();
                    }
                }
            });

            var ret = $('<table><tr><td colspan="3"><h1></h1></td></tr>'+
            '<tr><td>isbn: '+data.isbn+'</td><td>price:'+data.price+'</td>'+
            '<td>available: '+data.on_stock+'</td></tr>'+
            '<tr><td colspan=3>category:'+category+'</td></tr>'+
            '<tr><td colspan=3>'+data.description+'</td></tr></table>');
            ret.find('h1').append(link);
            // reviews
            var writeReview = $('<a href="">write a review</a>')
              .click(function() {
                newReviewForm.toggle();
                return false;
            });
            ret = ret.add( $('<p></p>').append(writeReview)
              .addClass('p_newreview').hide() );
            ret = ret.add(newReviewForm);
            var reviews = $("<div></div>");
            reviews.hide();
            if (data.no_of_reviews > 0) {
                var showReviews = $('<a href="">show reviews'+
                  '('+data.no_of_reviews+')</a>').click(function() {
                    if ( ! reviews.is(":visible")) {
                        $.getJSON("controllers/reviews.php?book="+data.id,function(data) {
                            reviews.text("");
                            $.each(data.collection,function(i,data) {
                                reviews.append('<p>on&nbsp;'+data.created_at+
                                  '&nbsp;'+data.user.name+'&nbsp;wrote:</p>');
                                reviews.append("<p>"+data.text+"</p>");
                            });
                            reviews.toggle(1000);
                        });
                    } else {
                        reviews.toggle(1000);
                    }
                    return false;
                });
                ret = ret.add( $('<p></p>').append(showReviews) );
                ret = ret.add( reviews );
            }
            // shoping cart
            var addToCart = $('<a href="">add to my shopping cart '+
            '(<span class="cartQuantity">0</span>)</a>')
              .click(function() {
                ShoppingCart.buy(data.id);
                q = Number( addToCart.find('.cartQuantity').text() );
                q++;
                addToCart.find('.cartQuantity').text(q);
                return false;
            });
            ret = ret.add( $('<p></p>').append(addToCart)
              .addClass('p_addtocart').hide() );
            return ret;
        } else {
            return null;
        }
    };

    ret.showBook = function(id) {
        if (id == undefined) {
            window.location.hash = '';
            this.url = "controllers/books.php";
        } else {
            window.location.hash = '#'+$.param( { book: id } );
            this.url = "controllers/books.php?book="+id;
        }
        this.refreshRead();
    }

    ret.showCat = function(id) {
        if (id == undefined) {
            window.location.hash = '';
            this.url = "controllers/books.php";
        } else {
            window.location.hash = '#'+$.param( { cat: id } );
            this.url = "controllers/books.php?cat="+id;
        }
        this.refreshRead();
    }

    return ret;
}

function getCategoryListing(renderTo,url,bookListing) {
    var ret = new CRUDrenderer(renderTo,url);

    if (bookListing) {
        ret.bookListing = bookListing;
    }

    ret.readRenderer = function(type) {
        if (type == "wrapper") { 
            var link = $('<a href="">all</a>');
            link.click(function() {
                if (ret.bookListing) {
                    ret.bookListing.showCat();
                }
                return false;
            });
            return $('<ul class="catListing"/>')
                .append( ( $("<li>").append(link) ) );
        } else {
            return null;
        }
    }

    ret.recordRenderer = function(type,data) {
        if (type == "record") {
            var link = $('<a href="">'+data.name+'</a>');
            link.click(function() {
                if (ret.bookListing) {
                    ret.bookListing.showCat(data.id);
                }
                return false;
            });
            return $('<li></li>').append(link);
        } else {
            return null;
        }
    }

    return ret;
}
